Passed
Push — master ( 29f5b0...4c43c3 )
by Rafael S.
02:58
created

FIRLPF.constructor   A

Complexity

Conditions 4

Size

Total Lines 20
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 14
dl 0
loc 20
rs 9.7
c 0
b 0
f 0
1
/*
2
 * Copyright (c) 2019 Rafael da Silva Rocha.
3
 * Copyright (c) 2014 Florian Markert
4
 *
5
 * Permission is hereby granted, free of charge, to any person obtaining
6
 * a copy of this software and associated documentation files (the
7
 * "Software"), to deal in the Software without restriction, including
8
 * without limitation the rights to use, copy, modify, merge, publish,
9
 * distribute, sublicense, and/or sell copies of the Software, and to
10
 * permit persons to whom the Software is furnished to do so, subject to
11
 * the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be
14
 * included in all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
 *
24
 */
25
26
/**
27
 * @fileoverview FIR LPF. Based on the FIR LPF from Fili by Florian Markert.
28
 * @see https://github.com/rochars/wavefile
29
 * @see https://github.com/markert/fili.js
30
 */
31
32
/**
33
 * A FIR low pass filter.
34
 */
35
export class FIRLPF {
36
  
37
  /**
38
   * @param {number} order The order of the filter.
39
   * @param {number} sampleRate The sample rate.
40
   * @param {number} cutOff The cut off frequency.
41
   */
42
  constructor(order, sampleRate, cutOff) {
43
    let omega = 2 * Math.PI * cutOff / sampleRate;
44
    let dc = 0;
45
    this.filters = [];
46
    for (let i = 0; i <= order; i++) {
47
      if (i - order / 2 === 0) {
48
        this.filters[i] = omega;
49
      } else {
50
        this.filters[i] = Math.sin(omega * (i - order / 2)) / (i - order / 2);
51
        // Hamming window
52
        this.filters[i] *= (0.54 - 0.46 * Math.cos(2 * Math.PI * i / order));
53
      }
54
      dc = dc + this.filters[i];
55
    }
56
    // normalize
57
    for (let i = 0; i <= order; i++) {
58
      this.filters[i] /= dc;
59
    }
60
    this.z = this.initZ_();
61
  }
62
63
  /**
64
   * @param {number} sample A sample of a sequence.
65
   * @return {number}
66
   */
67
  filter(sample) {
68
    this.z.buf[this.z.pointer] = sample;
69
    let out = 0;
70
    for (let i = 0, len = this.z.buf.length; i < len; i++) {
71
      out += (
72
        this.filters[i] * this.z.buf[(this.z.pointer + i) % this.z.buf.length]);
73
    }
74
    this.z.pointer = (this.z.pointer + 1) % (this.z.buf.length);
75
    return out;
76
  }
77
78
  /**
79
   * Reset the filter.
80
   */
81
  reset() {
82
    this.z = this.initZ_();
83
  }
84
85
  /**
86
   * Return the default value for z.
87
   * @private
88
   */
89
  initZ_() {
90
    let r = [];
91
    for (let i = 0; i < this.filters.length - 1; i++) {
92
      r.push(0);
93
    }
94
    return {
95
      buf: r,
96
      pointer: 0
97
    };
98
  }
99
}
100